using BepuPhysics.Collidables;
#if MYCODE
using BepuUtilities.Vectors;
#else
using System.Numerics;
#endif

namespace BepuPhysics
{
    public struct BodyActivityDescription
    {
        /// <summary>
        /// 允许身体进入睡眠状态的平方速度阈值。这与dot(linearVelocity,linearVelocity)+dot(angularVelocity,angularVelocity)进行比较。
        /// </summary>
        public float SleepThreshold;
        /// <summary>
        /// 身体在成为睡眠候选者之前必须低于睡眠阈值的时间步数。
        /// 请注意,不能保证身体在达到此最低要求后立即入睡。
        /// </summary>
        public byte MinimumTimestepCountUnderThreshold;

        /// <summary>
        /// 创建正文活动说明。
        /// </summary>
        /// <param name="sleepThreshold">允许身体进入睡眠状态的平方速度阈值。这与dot(linearVelocity,linearVelocity)+dot(angularVelocity,angularVelocity)进行比较。</param>
        /// <param name="minimumTimestepCountUnderThreshold">身体在成为睡眠候选者之前必须低于睡眠阈值的时间步数。
        /// 请注意,不保证身体在达到此最低要求后立即进入睡眠状态。</param>
        public BodyActivityDescription(float sleepThreshold, byte minimumTimestepCountUnderThreshold = 32)
        {
            SleepThreshold = sleepThreshold;
            MinimumTimestepCountUnderThreshold = minimumTimestepCountUnderThreshold;
        }
    }

    /// <summary>
    /// 碰撞器身体描述
    /// </summary>
    public struct BodyDescription
    {
        public RigidPose Pose;
        public BodyInertia LocalInertia;
        public BodyVelocity Velocity;
        public CollidableDescription Collidable;
        public BodyActivityDescription Activity;

        // 凸面形状辅助对象。
        /// <summary>
        /// 根据形状的最小和最大半径计算形状的合理默认推测边距。
        /// </summary>
        /// <typeparam name="TShape">要计算推测边距的形状的类型。</typeparam>
        /// <param name="Shape">要计算推测边距的形状。</param>
        /// <Returns>给定形状的推测性边距。</Returns>
        public static float GetDefaultSpeculativeMargin<TShape>(in TShape shape) where TShape : struct, IConvexShape
        {
            shape.ComputeAngularExpansionData(out var maximumRadius, out var maximumAngularExpansion);
            var minimumRadius = maximumRadius - maximumAngularExpansion;
            return 0.1f * (float)System.Math.Sqrt(maximumRadius * minimumRadius);
        }

        /// <summary>
        /// 计算形状的像样的默认活动描述。
        /// </summary>
        /// <typeparam name="TShape">要为其创建活动说明的形状的类型。</typeparam>
        /// <param name="Shape">要为其创建活动说明的形状。</param>
        /// <return>给定形状的默认活动说明。</return>
        public static BodyActivityDescription GetDefaultActivity<TShape>(in TShape shape) where TShape : struct, IConvexShape
        {
            BodyActivityDescription activity;
            activity.MinimumTimestepCountUnderThreshold = 32;
            shape.ComputeAngularExpansionData(out var maximumRadius, out var maximumAngularExpansion);
            var minimumRadius = maximumRadius - maximumAngularExpansion;
            activity.SleepThreshold = minimumRadius * minimumRadius * 0.1f;
            return activity;
        }

        /// <summary>
        /// 创建动态实体描述。
        /// </summary>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="惯性">身体的局部惯性。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateDynamic(in RigidPose pose, in BodyVelocity velocity, in BodyInertia inertia, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = pose, Velocity = velocity, LocalInertia = inertia, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建初始速度为零的动力学实体描述。
        /// </summary>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="惯性">身体的局部惯性。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateDynamic(in RigidPose pose, in BodyInertia inertia, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = pose, LocalInertia = inertia, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建具有标识方向的动态实体描述。
        /// </summary>
        /// <param name="position">正文的位置。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="惯性">身体的局部惯性。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateDynamic(in Vector3 position, in BodyVelocity velocity, in BodyInertia inertia, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = new RigidPose(position), Velocity = velocity, LocalInertia = inertia, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建初始速度和身份方向为零的动力学实体描述。
        /// </summary>
        /// <param name="position">正文的位置。</param>
        /// <param name="inertia">身体的局部惯性。</param>
        /// <param name="collidable">可碰撞以与正文关联。</param>
        /// <param name="activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateDynamic(in Vector3 position, in BodyInertia inertia, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = new RigidPose(position), LocalInertia = inertia, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 使用从凸形生成的可碰撞描述、惯性描述和活动描述创建动力学实体描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="mass">主体的质量。将根据此质量和形状计算惯性张量。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexDynamic<TConvexShape>(
            in RigidPose pose, in BodyVelocity velocity, float mass, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            var description = new BodyDescription
            {
                Pose = pose,
                Velocity = velocity,
                Activity = GetDefaultActivity(shape),
                Collidable = new CollidableDescription(shapes.Add(shape), GetDefaultSpeculativeMargin(shape))
            };
            shape.ComputeInertia(mass, out description.LocalInertia);
            return description;
        }

        /// <summary>
        /// 创建具有身份方向的动态身体描述,以及从凸形生成的可碰撞、惯性和活动描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="position">正文的位置。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="mass">主体的质量。将根据此质量和形状计算惯性张量。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexDynamic<TConvexShape>(
            in Vector3 position, in BodyVelocity velocity, float mass, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexDynamic(new RigidPose(position), velocity, mass, shapes, shape);
        }

        /// <summary>
        /// 创建初始速度为零的动力学实体描述,以及从凸形生成的可碰撞描述、惯性描述和活动描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="mass">主体的质量。将根据此质量和形状计算惯性张量。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexDynamic<TConvexShape>(
            in RigidPose pose, float mass, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexDynamic(pose, default, mass, shapes, shape);
        }

        /// <summary>
        /// 创建初始速度为零、身份方向为零以及从凸形生成的可碰撞、惯性和活动描述的动力学实体描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="position">正文的位置。</param>
        /// <param name="mass">主体的质量。将根据此质量和形状计算惯性张量。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexDynamic<TConvexShape>(
            in Vector3 position, float mass, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexDynamic(new RigidPose(position), default, mass, shapes, shape);
        }

        /// <summary>
        /// 创建运动学实体描述。
        /// </summary>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateKinematic(in RigidPose pose, in BodyVelocity velocity, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = pose, Velocity = velocity, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建初始速度为零的运动学实体描述。
        /// </summary>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateKinematic(in RigidPose pose, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = pose, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建具有标识方向的运动学实体描述。
        /// </summary>
        /// <param name="position">正文的位置。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateKinematic(in Vector3 position, in BodyVelocity velocity, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = new RigidPose(position), Velocity = velocity, Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 创建具有身份方向和零初始速度的运动学实体描述。
        /// </summary>
        /// <param name="position">正文的位置。</param>
        /// <param name="Collisible">可碰撞以与正文关联。</param>
        /// <param name="Activity">正文的活动设置。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateKinematic(in Vector3 position, in CollidableDescription collidable, in BodyActivityDescription activity)
        {
            return new BodyDescription { Pose = new RigidPose(position), Activity = activity, Collidable = collidable };
        }

        /// <summary>
        /// 使用从凸形生成的可碰撞描述和活动描述创建运动学实体描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexKinematic<TConvexShape>(
            in RigidPose pose, in BodyVelocity velocity, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            var description = new BodyDescription
            {
                Pose = pose,
                Velocity = velocity,
                Activity = GetDefaultActivity(shape),
                Collidable = new CollidableDescription(shapes.Add(shape), GetDefaultSpeculativeMargin(shape))
            };
            return description;
        }

        /// <summary>
        /// 创建具有身份方向的运动学实体描述,以及从凸形生成的可碰撞描述和活动描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="position">正文的位置。</param>
        /// <param name="ocity">物体的初始速度。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexKinematic<TConvexShape>(
            in Vector3 position, in BodyVelocity velocity, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexKinematic(new RigidPose(position), velocity, shapes, shape);
        }

        /// <summary>
        /// 创建初始速度为零的运动学实体描述以及从凸形生成的可碰撞描述和活动描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="pose">正文的姿势。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexKinematic<TConvexShape>(
            in RigidPose pose, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexKinematic(pose, default, shapes, shape);
        }

        /// <summary>
        /// 创建初始速度为零、身份方向为零的运动学实体描述,以及从凸形生成的可碰撞描述和活动描述。将形状添加到给定的形状集中。
        /// </summary>
        /// <typeparam name="TConvexShape">要为其创建正文的形状的类型。</typeparam>
        /// <param name="position">正文的位置。</param>
        /// <param name="Shares">要将形状添加到的形状集合。</param>
        /// <param name="Shape">要添加到形状集并从中创建正文的形状。</param>
        /// <return>正文的构造说明。</return>
        public static BodyDescription CreateConvexKinematic<TConvexShape>(
            in Vector3 position, Shapes shapes, in TConvexShape shape)
            where TConvexShape : unmanaged, IConvexShape
        {
            return CreateConvexKinematic(new RigidPose(position), default, shapes, shape);
        }

    }


}
